#include <fmt/printf.h>
#include <unistd.h>

#include "plugin/plugin_executor.h"
#include "util/logger.h"

using namespace kawauso;

// AbstractPluginExecutor start from here

AbstractPluginExecutor::AbstractPluginExecutor()
        : forkValue(fork())
{
    info("{}", forkValue);
}

AbstractPluginExecutor::AbstractPluginExecutor(AbstractPluginExecutor &&) noexcept {
    //
}

AbstractPluginExecutor::~AbstractPluginExecutor() {
    //
}

// JavaPluginExecutor start from here

JavaPluginExecutor::JavaPluginExecutor()
        : javaVM(nullptr)
        , jniEnv(nullptr)
{
    if (forkValue == 0) {
        return;
    }

    JavaVMInitArgs initArgs;
    initArgs.version = JNI_VERSION_10;
    initArgs.nOptions = 0;
    initArgs.ignoreUnrecognized = JNI_TRUE;

    if (JNI_CreateJavaVM(&javaVM, (void**)&jniEnv, &initArgs) != 0) {
        error("JVM启动失败！");
        exit(EXIT_FAILURE);
    }

    info("JVM启动成功！");
}

JavaPluginExecutor::JavaPluginExecutor(JavaPluginExecutor &&x) noexcept
        : javaVM(nullptr)
        , jniEnv(nullptr)
{
    std::swap(javaVM, x.javaVM);
    std::swap(jniEnv, x.jniEnv);
}

JavaPluginExecutor::~JavaPluginExecutor() {
    if (javaVM != nullptr) {
        javaVM->DestroyJavaVM();
    }
}

void func(JNIEnv *env, jobject thiz) {
    info("{}", fmt::ptr(env));
}

void JavaPluginExecutor::test() {
    jclass startClass = jniEnv->FindClass("Main");
    if (startClass != nullptr) {
        jmethodID methodId = jniEnv->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
        JNINativeMethod method[] = {
                {"test", "()V", (void*)&func}
        };
        jniEnv->RegisterNatives(startClass, method, 1);
        info("{}", jniEnv->ExceptionCheck() == JNI_TRUE);
        jniEnv->CallStaticVoidMethod(startClass, methodId, nullptr);
        info("{}", jniEnv->ExceptionCheck() == JNI_TRUE);
        javaVM->DetachCurrentThread();
    } else {
        error("没有找到启动类");
    }
}